
public class Viterbi {
	public double GetMax3(double Num1, double Num2, double Num3){
		//Get Maximum Value of Three Number
		double tmp;
		if(Num1>Num2){
			tmp=Num1;
		}
		else{
			tmp=Num2;
		}
		if(tmp < Num3){
			tmp=Num3;
		}
		return tmp;
	}
	public double GetMax2(double Num1, double Num2){
		//Get Maximum Value of Two Number
		if(Num1>Num2){
			return Num1; 
		}
		else{
			return Num2;
		}
	}
	
	public double ViterbiAlgorithm(ProteinSeq Sequence,HMMProfile ProteinProfile){
		int SeqLen=Sequence.GetArraySize();
		int ProfileLen=ProteinProfile.GetProfileSize();
		double M[][]=new double[SeqLen+1][ProfileLen+1];// M Score
		double I[][]=new double[SeqLen+1][ProfileLen+1];// I Score
		double D[][]=new double[SeqLen+1][ProfileLen+1];// D Score
		M[0][0]=I[0][0]=D[0][0]=0;// Initialization Score
		int i=0;
		int t=0;
		double XE=0;
		while(i<SeqLen){
			// First Loop: per Amoni per time
			int Amoni=Sequence.GetAmoni(i);//Get Current AMoni;
			i++;
			t++;
			M[t][0]=I[t][0]=D[t][0]=0;
			int j;
				for(j=1;j<ProfileLen;j++){
					//Second Loop: per Node per time
					M[0][j]=I[0][j]=D[0][j]=0;
					// Calculating M Score
					double m_m=M[t-1][j-1]+ProteinProfile.GetTranProbability(j-1,0);
					double i_m=I[t-1][j-1]+ProteinProfile.GetTranProbability(j-1, 3);
					double d_m=D[t-1][j-1]+ProteinProfile.GetTranProbability(j-1,5);
					double Max_M=GetMax3(m_m,i_m,d_m);
					double t1=ProteinProfile.GetMatchProbability(j-1,Amoni);
					M[t][j]=Max_M+t1;
					
					
					//Calculating I Score
					double m_i=M[t-1][j]+ProteinProfile.GetTranProbability(j-1, 1);
					double i_i=M[t-1][j]+ProteinProfile.GetTranProbability(j-1,4);
					double Max_I=GetMax2(m_i,i_i);
					I[t][j]=Max_I+ProteinProfile.GetInsertProbability(j-1, Amoni);
					
					//Calculating D Score
					double m_d=M[t][j-1]+ProteinProfile.GetTranProbability(j-1, 2);
					double d_d=D[t][j-1]+ProteinProfile.GetTranProbability(j-1, 6);
					D[t][j]=GetMax2(m_d,d_d);
				}// End of For Loop
				if(M[t][j-1]>XE){
					XE=M[t][j-1];
				}
			}// End of While LOOP
		//Return calculation Score
		return XE;
	}// End of Viterbi Algorithm
	/*
	public static void main(String[] args) {

	}
	*/
}